package com.hupu.jrs.ui.thread.list

import android.text.TextUtils
import android.view.View
import com.hupu.jrs.injector.PerActivity
import com.hupu.jrs.util.ToastUtil
import java.text.SimpleDateFormat
import java.util.ArrayList
import java.util.Date
import javax.inject.Inject
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.functions.Action1
import rx.functions.Func1
import rx.schedulers.Schedulers
import rx.subjects.PublishSubject

/**
 * Created by sll on 2016/3/9.
 */
@PerActivity
class ThreadListPresenter @Inject
constructor(private val fid: String, private val mThreadRepository: ThreadRepository, private val mGameApi: GameApi,
            private val mUserStorage: UserStorage, private val mForumApi: ForumApi, private val mForumDao: ForumDao) : ThreadListContract.Presenter {

    private var isFirst = true
    private val mThreadSubject: PublishSubject<List<Thread>>
    private var mThreadListView: ThreadListContract.View? = null
    private var threads: MutableList<Thread> = ArrayList()

    private var lastTid = ""
    private var lastTamp = ""
    private var type: String? = null
    private var pageIndex: Int = 0
    private var loadType = TYPE_LIST
    private var key: String? = null
    private var hasNextPage = true
    private var isAttention = false

    private var mSubscription: Subscription? = null

    private val isLogin: Boolean
        get() {
            if (!mUserStorage.isLogin()) {
                mThreadListView!!.showLoginUi()
                return false
            }
            return true
        }

    init {
        mThreadSubject = PublishSubject.create()
    }

    override fun onThreadReceive(type: String) {
        mThreadListView!!.showLoading()
        mThreadListView!!.onFloatingVisibility(View.VISIBLE)
        this.type = type
        loadType = TYPE_LIST
        mThreadRepository.getThreadListObservable(Integer.valueOf(fid), mThreadSubject)
                .subscribe(Action1<List<Thread>> { threads ->
                    this@ThreadListPresenter.threads = threads
                    if (threads.isEmpty()) {
                        if (!isFirst) {
                            mThreadListView!!.onError("数据加载失败")
                        }
                        isFirst = false
                    } else {
                        mThreadListView!!.showContent()
                        lastTid = threads[threads.size - 1].getTid()
                        mThreadListView!!.renderThreads(threads)
                    }
                })
        loadThreadList("")
        getAttendStatus()
    }

    override fun onStartSearch(key: String, page: Int) {
        if (TextUtils.isEmpty(key)) {
            mThreadListView!!.showToast("搜索词不能为空")
            return
        }
        mThreadListView!!.showLoading()
        mThreadListView!!.onFloatingVisibility(View.GONE)
        pageIndex = page
        this.key = key
        loadSearchList()
    }

    private fun loadThreadList(last: String) {
        mSubscription = mThreadRepository.getThreadsList(fid, last, lastTamp, type, mThreadSubject)
                .subscribe(Action1<Any> { threadListData ->
                    if (threadListData != null && threadListData.result != null) {
                        val data = threadListData.result
                        lastTamp = data.stamp
                        hasNextPage = data.nextPage
                        if (TextUtils.isEmpty(last)) {
                            mThreadListView!!.onScrollToTop()
                        }
                    }
                    mThreadListView!!.onRefreshCompleted()
                    mThreadListView!!.onLoadCompleted(hasNextPage)
                }, Action1<Throwable> {
                    if (threads.isEmpty()) {
                        mThreadListView!!.onError("数据加载失败，请重试")
                    } else {
                        mThreadListView!!.onRefreshCompleted()
                        mThreadListView!!.onLoadCompleted(hasNextPage)
                        ToastUtil.showToast("数据加载失败，请重试")
                    }
                })
    }

    private fun loadSearchList() {
        loadType = TYPE_SEARCH
        mGameApi.search(key, fid, pageIndex).map(Func1<Any, List<Thread>> { searchData ->
            if (searchData != null) {
                if (pageIndex == 1) {
                    threads.clear()
                }
                val result = searchData.result
                hasNextPage = result.hasNextPage === 1
                for (search in result.data) {
                    val thread = Thread()
                    thread.setFid(search.fid)
                    thread.setTid(search.id)
                    thread.setLightReply(Integer.valueOf(search.lights))
                    thread.setReplies(search.replies)
                    thread.setUserName(search.username)
                    thread.setTitle(search.title)
                    val time = java.lang.Long.valueOf(search.addtime)
                    val date = Date(time)
                    val format = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
                    thread.setTime(format.format(date))
                    threads.add(thread)
                }
                return@Func1 threads
            }
            null
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(Action1<List<Thread>> { threads ->
            if (threads == null) {
                loadThreadError()
            } else {
                if (threads.isEmpty()) {
                    mThreadListView!!.onEmpty()
                } else {
                    mThreadListView!!.showContent()
                    mThreadListView!!.renderThreads(threads)
                    mThreadListView!!.onRefreshCompleted()
                    mThreadListView!!.onLoadCompleted(hasNextPage)
                    if (pageIndex == 1) {
                        mThreadListView!!.onScrollToTop()
                    }
                }
            }
        }, Action1<Throwable> { loadThreadError() })
    }

    private fun loadThreadError() {
        if (threads.isEmpty()) {
            mThreadListView!!.onError("数据加载失败")
        } else {
            mThreadListView!!.showContent()
            mThreadListView!!.onRefreshCompleted()
            mThreadListView!!.onLoadCompleted(true)
            mThreadListView!!.showToast("数据加载失败")
        }
    }

    private fun getAttendStatus() {
        mForumApi.getAttentionStatus(fid)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(Action1<Any> { attendStatusData ->
                    if (attendStatusData != null && attendStatusData.status === 200) {
                        mThreadListView!!.renderThreadInfo(attendStatusData.forumInfo)
                        isAttention = attendStatusData.attendStatus === 1
                        mThreadListView!!.attendStatus(isAttention)
                    }
                }, Action1<Throwable> { getForumInfo() })
    }

    private fun getForumInfo() {
        Observable.create<Forum> { subscriber ->
            val forumList = mForumDao.queryBuilder().where(ForumDao.Properties.Fid.eq(fid)).list()
            if (!forumList.isEmpty()) {
                subscriber.onNext(forumList.get(0))
            }
        }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { forum ->
                    if (forum != null && mThreadListView != null) {
                        mThreadListView!!.renderThreadInfo(forum)
                    }
                }
    }

    override fun onAttentionClick() {
        if (isLogin) {
            if (isAttention) {
                delAttention()
            } else {
                addAttention()
            }
        }
    }

    override fun onPostClick() {
        if (isLogin) {
            mThreadListView!!.showPostThreadUi(fid)
        }
    }

    private fun addAttention() {
        mForumApi.addAttention(fid)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(Action1<Any> { result ->
                    if (result.status === 200 && result.result === 1) {
                        mThreadListView!!.showToast("添加关注成功")
                        isAttention = result.status === 200
                        mThreadListView!!.attendStatus(isAttention)
                    }
                }, Action1<Throwable> { mThreadListView!!.showToast("添加关注失败，请检查网络后重试") })
    }

    private fun delAttention() {
        mForumApi.delAttention(fid)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(Action1<Any> { result ->
                    if (result.status === 200 && result.result === 1) {
                        mThreadListView!!.showToast("取消关注成功")
                        isAttention = result.status !== 200
                        mThreadListView!!.attendStatus(isAttention)
                    }
                }, Action1<Throwable> { mThreadListView!!.showToast("取消关注失败，请检查网络后重试") })
    }

    override fun onRefresh() {
        mThreadListView!!.onScrollToTop()
        if (loadType == TYPE_LIST) {
            loadThreadList("")
        } else {
            pageIndex = 1
            loadSearchList()
        }
    }

    override fun onReload() {
        mThreadListView!!.showContent()
        mThreadListView!!.showLoading()
        if (loadType == TYPE_LIST) {
            loadThreadList(lastTid)
        } else {
            loadSearchList()
        }
    }

    override fun onLoadMore() {
        if (!hasNextPage) {
            mThreadListView!!.showToast("没有更多了~")
            mThreadListView!!.onLoadCompleted(false)
            return
        }

        if (loadType == TYPE_LIST) {
            loadThreadList(lastTid)
        } else {
            pageIndex++
            loadSearchList()
        }
    }

    fun attachView(view: ThreadListContract.View) {
        mThreadListView = view
        mThreadListView!!.showProgress()
    }

    fun detachView() {
        if (mSubscription != null && !mSubscription!!.isUnsubscribed) {
            mSubscription!!.unsubscribe()
        }
        mThreadListView = null
    }

    companion object {

        private val TYPE_LIST = 1
        private val TYPE_SEARCH = 2
    }
}
